#pragma once

#include "LinkedList.h"

template<typename DATA_TYPE>
LinkedList<DATA_TYPE>::LinkedList(){
	RenewRoot();
};
template<typename DATA_TYPE>
LinkedList<DATA_TYPE>::~LinkedList(){};

template<typename DATA_TYPE>
int LinkedList<DATA_TYPE>::Get_Size(){
	int t_size = 0;
	do{
		Node *t_node = m_root;
		if(!t_node){
			break;
		}
		while(t_node->m_next){
			t_node = t_node->m_next;
			t_size++;
		}
	}while(false);
	return t_size;
};

template<typename DATA_TYPE>
void LinkedList<DATA_TYPE>::Remove_FromEnd(){
	Node *t_node = m_root;
	while(t_node->m_next){
		t_node = t_node->m_next;
	}
	t_node->m_prev->m_next = 0;
	if(t_node){
		delete t_node;
		t_node = 0;
	}
};

template<typename DATA_TYPE>
void LinkedList<DATA_TYPE>::Insert_ToEnd(DATA_TYPE a_data){
	Node *t_node = m_root;
	if(!t_node){
		RenewRoot();
		t_node = m_root;
	}
	while(t_node->m_next){
		t_node = t_node->m_next;
	}
	Node *t_nodeToInsert = new Node;
	t_nodeToInsert->m_data = a_data;
	t_nodeToInsert->m_next = 0;
	t_nodeToInsert->m_prev = t_node;
	t_node->m_next = t_nodeToInsert;
	//t_nodeToInsert = 0;
};

template<typename DATA_TYPE>
void LinkedList<DATA_TYPE>::Remove_FromIndex(unsigned int a_index){
	int t_size = 0;
	Node *t_node = m_root;
	while(t_node->m_next){
		t_node = t_node->m_next;
		if(t_size == a_index){
			break;
		}
		t_size++;
	}

	Node *t_nodePrevious = t_node->m_prev;
	t_nodePrevious->m_next = t_node->m_next;
	if(t_node->m_next){
		t_node->m_next->m_prev = t_nodePrevious;
	}
	if(t_node){
		delete t_node;
		t_node = 0;
	}
};

template<typename DATA_TYPE>
DATA_TYPE LinkedList<DATA_TYPE>::Get_Data(unsigned int a_index){
	int t_size = 0;
	Node *t_node = m_root;
	while(t_node->m_next){
		t_node = t_node->m_next;
		if(t_size == a_index){
			break;
		}
		t_size++;
	}

	return t_node->m_data;
};

template<typename DATA_TYPE>
void LinkedList<DATA_TYPE>::Clear(){
	ClearList(m_root->m_data);
};

template<typename DATA_TYPE>
void LinkedList<DATA_TYPE>::RenewRoot(){
	m_root = new Node;
	//m_root->m_data = 12007;
	m_root->m_next = 0;
	m_root->m_prev = 0;
};

template<typename DATA_TYPE>
void LinkedList<DATA_TYPE>::ClearList(DATA_TYPE a_DATA_TYPE){
	Node *t_node = m_root;
	if(t_node->m_next){
		while(t_node->m_next){
			//t_node = t_node->m_next;
			Node *t_nodeToRemove = t_node;
			t_node = t_node->m_next;
			delete t_nodeToRemove;
			t_nodeToRemove = 0;
			if(t_nodeToRemove){
				delete t_nodeToRemove;
				t_nodeToRemove = 0;
			}
		}
		if(t_node){
			delete t_node;
			t_node = 0;
		}
	}
	m_root = 0;
};

/***************************************************************************************************/

template<typename DATA_TYPE>
LinkedList<DATA_TYPE *>::LinkedList(){
	RenewRoot();
};
template<typename DATA_TYPE>
LinkedList<DATA_TYPE *>::~LinkedList(){};

template<typename DATA_TYPE>
int LinkedList<DATA_TYPE *>::Get_Size(){
	int t_size = 0;
	do{
		Node *t_node = m_root;
		if(!t_node){
			break;
		}
		while(t_node->m_next){
			t_node = t_node->m_next;
			t_size++;
		}
	}while(false);
	return t_size;
};

template<typename DATA_TYPE>
void LinkedList<DATA_TYPE *>::Remove_FromEnd(){
	Node *t_node = m_root;
	while(t_node->m_next){
		t_node = t_node->m_next;
	}
	t_node->m_prev->m_next = 0;
	if(t_node->m_data){
		delete t_node->m_data;
		t_node->m_data = 0;
	}
	if(t_node){
		delete t_node;
		t_node = 0;
	}
};

template<typename DATA_TYPE>
void LinkedList<DATA_TYPE *>::Remove_FromEndPtr(unsigned int a_index){
	Node *t_node = m_root;
	while(t_node->m_next){
		t_node = t_node->m_next;
	}
	t_node->m_prev->m_next = 0;
	//if(t_node->m_data){
	//	delete t_node->m_data;
	//	t_node->m_data = 0;
	//}
	if(t_node){
		delete t_node;
		t_node = 0;
	}
};

template<typename DATA_TYPE>
void LinkedList<DATA_TYPE *>::Insert_ToEnd(DATA_TYPE *a_data){
	Node *t_node = m_root;
	if(!t_node){
		RenewRoot();
		t_node = m_root;
	}
	while(t_node->m_next){
		t_node = t_node->m_next;
	}
	Node *t_nodeToInsert = new Node;
	t_nodeToInsert->m_data = a_data;
	t_nodeToInsert->m_next = 0;
	t_nodeToInsert->m_prev = t_node;
	t_node->m_next = t_nodeToInsert;
	//t_nodeToInsert = 0;
};

template<typename DATA_TYPE>
void LinkedList<DATA_TYPE *>::Remove_FromIndex(unsigned int a_index){
	int t_size = 0;
	Node *t_node = m_root;
	while(t_node->m_next){
		t_node = t_node->m_next;
		if(t_size == a_index){
			break;
		}
		t_size++;
	}

	Node *t_nodePrevious = t_node->m_prev;
	t_nodePrevious->m_next = t_node->m_next;
	if(t_node->m_next){
		t_node->m_next->m_prev = t_nodePrevious;
	}
	if(t_node->m_data){
		delete t_node->m_data;
		t_node->m_data = 0;
	}
	if(t_node){
		delete t_node;
		t_node = 0;
	}
};

template<typename DATA_TYPE>
void LinkedList<DATA_TYPE *>::Remove_FromIndexPtr(unsigned int a_index){
	int t_size = 0;
	Node *t_node = m_root;
	while(t_node->m_next){
		t_node = t_node->m_next;
		if(t_size == a_index){
			break;
		}
		t_size++;
	}

	Node *t_nodePrevious = t_node->m_prev;
	t_nodePrevious->m_next = t_node->m_next;
	if(t_node->m_next){
		t_node->m_next->m_prev = t_nodePrevious;
	}
	//if(t_node->m_data){
	//	delete t_node->m_data;
	//	t_node->m_data = 0;
	//}
	if(t_node){
		delete t_node;
		t_node = 0;
	}
};

template<typename DATA_TYPE>
DATA_TYPE *LinkedList<DATA_TYPE *>::Get_Data(unsigned int a_index){
	int t_size = 0;
	Node *t_node = m_root;
	while(t_node->m_next){
		t_node = t_node->m_next;
		if(t_size == a_index){
			break;
		}
		t_size++;
	}

	return t_node->m_data;
};

template<typename DATA_TYPE>
void LinkedList<DATA_TYPE *>::Clear(){
	ClearList(m_root->m_data);
};

template<typename DATA_TYPE>
void LinkedList<DATA_TYPE *>::RenewRoot(){
	m_root = new Node;
	m_root->m_data = 0;
	m_root->m_next = 0;
	m_root->m_prev = 0;
};

template<typename DATA_TYPE>
void LinkedList<DATA_TYPE *>::ClearList(DATA_TYPE *&a_DATA_TYPE){
	Node *t_node = m_root;
	if(t_node){
		while(t_node->m_next){
			Node *t_nodeToRemove = t_node;
			t_node = t_node->m_next;
			if(t_nodeToRemove->m_data){
				delete t_nodeToRemove->m_data;
				t_nodeToRemove->m_data = 0;
			}
			if(t_nodeToRemove){
				delete t_nodeToRemove;
				t_nodeToRemove = 0;
			}
		}
		if(t_node->m_data){
			delete t_node->m_data;
			t_node->m_data = 0;
		}
		if(t_node){
			delete t_node;
			t_node = 0;
		}
	}
	m_root = 0;
};

template<typename DATA_TYPE>
void LinkedList<DATA_TYPE *>::ClearPtr(){
	Node *t_node = m_root;
	if(t_node){
		while(t_node->m_next){
			Node *t_nodeToRemove = t_node;
			t_node = t_node->m_next;
			if(t_nodeToRemove){
				delete t_nodeToRemove;
				t_nodeToRemove = 0;
			}
		}
	}
	if(t_node){
		delete t_node;
		t_node = 0;
	}
	m_root = 0;
};